package com.yeqing.client;

import com.alibaba.fastjson.JSONObject;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;

public class AppClientHello {

    private final String host;
    private final int port;
    private final String msg;

    public AppClientHello(String host, int port, String msg) {
        this.host = host;
        this.port = port;
        this.msg = msg;
    }

    public void run() throws InterruptedException {

        // IO 线程池
        EventLoopGroup group = new NioEventLoopGroup();

        try {
            // 客户端辅助启动类
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(group)
                    // 实例化一个Channel
                    .channel(NioSocketChannel.class)
                    .remoteAddress(host, port)
                    // 进行通道初始化配置 如果有多个handler，都在这里进行
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            // 添加自定义的 Handler
                            // 连接建立后，都会自动创建一个管道 pipeline,这个管道也叫做责任链，保证顺序执行，
                            // 同时又可以灵活的配置各类 Handler，这是一个很精妙的设计，
                            // 既减少了线程切换带来的资源开销、避免好多麻烦事，同时性能又得到了极大增强
                            socketChannel.pipeline().addLast(new HandlerClientHello());
                        }
                    });

            // 连接到远程节点，等待连接完成 sync()表示采用的同步方法，这样连接建立成功后，才继续往下执行
            ChannelFuture future = bootstrap.connect().sync();

            // 发送消息到服务器端，编码格式是 UTF-8
            future.channel().writeAndFlush(Unpooled.copiedBuffer(msg, io.netty.util.CharsetUtil.UTF_8));
            // 阻塞操作，closeFuture()开启了一个channel的监听器（这期间channel在进行各项工作），直到链路断开
            future.channel().closeFuture().sync();
        } finally {
            group.shutdownGracefully().sync();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("name", "yeqing");
        jsonObject.put("age", "25");
        new AppClientHello("127.0.0.1", 18080, jsonObject.toJSONString()).run();
    }
}
